package formatter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Responsible for writing objects into its appropriate formatter
 * @author dolphinigle
 */
public class CodeforcesFormatter implements Formatter {

  /**
   * Base path. For example, problemset/irvan/
   */
  protected String base_path_;

  /**
   * True iff codeforces formatter is currently opening a file
   */
  protected boolean file_opened_;

  /**
   * The next number of test case to be written.
   */
  protected int next_filename_count_;

  /**
   * Output Stream writer
   */
  protected BufferedWriter writer_;

  /**
   * Constructs a new codeforces formatter
   * @param writer output stream capsulator to write to
   */
  public CodeforcesFormatter(String base_path, int init_filename_count_) {
    assert base_path.endsWith("/");
    base_path_ = base_path;
    next_filename_count_ = init_filename_count_;
  }

  /**
   * Closes the output stream associated with this formatter
   * @throws IOException iff closing fails
   */
  public void close() {
    assert file_opened_;
    file_opened_ = false;
    try {
      writer_.close();
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Opens the output
   */
  public void open() {
    assert !file_opened_;
    file_opened_ = true;
    String filename = base_path_ + String.valueOf(next_filename_count_) + ".in";
    ++next_filename_count_;
    try {
      this.writer_ = new BufferedWriter(new FileWriter(filename));
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  public void nl() {
    assert file_opened_;
    this.write("\n");
  }

  public void writeSpaceSeparatedInts(int... numbers) {
    assert file_opened_;
    boolean init = true;
    for (int i : numbers) {
      if (!init) {
        this.write(" ");
      }
      init = false;
      this.writeInt(i);
    }
  }

  public void write(String str) {
    assert file_opened_;
    try {
      writer_.write(str);
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Write an integer
   * @param param integer to be written
   */
  public void writeInt(int param) {
    assert file_opened_;
    try {
      writer_.write(String.valueOf(param));
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Write a long
   * @param param long to be written
   */
  public void writeLong(long param) {
    assert file_opened_;
    try {
      writer_.write(String.valueOf(param));
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Write an array of integers, separated by param
   * @param param array of integers to be written
   */
  public void writeArrayInt(int[] param, String separator) {
    assert file_opened_;
    try {
      for (int i = 0; i < param.length; ++i) {
        if (i > 0) writer_.write(separator);
        writer_.write(String.valueOf(param[i]));
      }
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Write an array of longs, separated by input
   * @param param array of longs to be written
   */
  public void writeArrayLong(long[] param, String separator) {
    assert file_opened_;
    try {
      for (int i = 0; i < param.length; ++i) {
        if (i > 0) writer_.write(separator);
        writer_.write(String.valueOf(param[i]));
      }
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

  /**
   * Format and write an array of string
   * @param param array of string to be written
   */
  public void writeArrayString(String[] param, String separator) {
    assert file_opened_;
    try {
      for (int i = 0; i < param.length; ++i) {
        if (i > 0) writer_.write(separator);
        writer_.write(param[i]);
      }
    } catch (IOException ios) {
      throw new Error(ios.toString());
    }
  }

}
